package br.elsa.survey.services.impl.tests;

import static org.mockito.Matchers.any;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.security.InvalidParameterException;
import java.util.List;

import javax.enterprise.event.Event;

import junit.framework.Assert;

import org.junit.Before;
import org.junit.Test;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import br.elsa.survey.dao.QuestionDao;
import br.elsa.survey.dao.exceptions.DataNotFoundException;
import br.elsa.survey.domain.questions.Question;
import br.elsa.survey.services.events.QuestionCreatedEvent;
import br.elsa.survey.services.events.QuestionRemovedEvent;
import br.elsa.survey.services.impl.QuestionServiceBean;

/**
 * TDD class for {@link QuestionServiceBean} class
 * 
 * @author diego
 * @since 2010-10-25
 */
public class QuestionServiceBeanTest {

	/**
	 * class under test
	 */
	private QuestionServiceBean questionService;

	@Mock
	private QuestionDao questionsDao;

	@Mock
	private Event<QuestionCreatedEvent> questionCreatedEvent;

	@Mock
	private Event<QuestionRemovedEvent> questionRemovedEvent;

	@Mock
	private Question question;

	@Before
	public void setUp() throws Exception {
		MockitoAnnotations.initMocks(this);
		this.questionService = new QuestionServiceBean(questionsDao, questionCreatedEvent, questionRemovedEvent);
	}

	@Test(expected = InvalidParameterException.class)
	public void createShouldThrowInvalidParameterExceptionIfQuestionIsNull() {
		questionService.create(null);
	}

	@Test
	public void createShouldInvokeQuestionsDaoCreateAndFireQuestionCreatedEvent() {
		questionService.create(question);

		InOrder inOrder = inOrder(questionsDao, questionCreatedEvent);
		inOrder.verify(questionsDao, times(1)).insert(question);
		inOrder.verify(questionCreatedEvent, times(1)).fire(any(QuestionCreatedEvent.class));
	}

	@Test
	public void getAllQuestionsShouldCallQuestionsDaoFindAllMethodToRetrieveDatabaseData() throws DataNotFoundException {

		questionService.getAllQuestions();

		verify(questionsDao, times(1)).findAll();
	}

	@Test
	public void getAllQuestionsShouldReturnQuestionsDaoFindAllMethodResult() throws DataNotFoundException {

		List<Question> questions = mock(List.class);
		when(questionsDao.findAll()).thenReturn(questions);
		List<Question> result = questionService.getAllQuestions();

		Assert.assertEquals(questions, result);
	}

	@Test(expected = DataNotFoundException.class)
	public void getAllQuestionsShouldThrowDataNotFoundExceptionIfNoQuestionIsFound() throws DataNotFoundException {

		when(questionsDao.findAll()).thenThrow(new DataNotFoundException());
		questionService.getAllQuestions();
	}

	@Test
	public void removeShouldCallQuestionsDaoBeanDeleteMethodWithSameParameterAndThrowsQuestionRemovedEventInThisOrder() {

		InOrder inOrder = inOrder(questionsDao, questionRemovedEvent);

		questionService.remove(question);

		inOrder.verify(questionsDao, times(1)).delete(question);
		inOrder.verify(questionRemovedEvent, times(1)).fire(any(QuestionRemovedEvent.class));
	}

	@Test(expected = InvalidParameterException.class)
	public void removeShouldThrowInvalidParameterExceptionWhenParameterIsNull() {

		questionService.remove(null);
	}
}
